#include <stdio.h>
#include <stdlib.h>

#include "lru.h"

int values[] = { 88, 56, 100, 2, 25 };

// -- test lru
typedef struct {
        int chkid;
} rcache_entry_t;

static uint32_t __lru_key_func(const void *key) {
        int _key = *(int *)key;
        return (uint32_t)_key;
}

static void* __lru_get_key_func(void *entry) {
        rcache_entry_t *_entry = entry;
        return &_entry->chkid;
}

static int __lru_cmp_func(const void *entry, const void *key) {
        const rcache_entry_t *_entry = entry;
        int _key = *(int *)key;

        return (_entry->chkid - _key) < 0;
}

static int __lru_load(void *key, void **value) {
        int ret;
        int chkid = *(int *)key;
        rcache_entry_t *entry;

        ret = ymalloc((void **)&entry, sizeof(rcache_entry_t));
        if (unlikely(ret))
                GOTO(err_ret, ret);

        entry->chkid = chkid;

        *value = entry;
        return 0;
err_ret:
        return ret;
}

static int __lru_free(void *lru_entry) {
        lru_entry_t *entry = (lru_entry_t *)lru_entry;
        rcache_entry_t *rc_ent = entry->value;

        yfree((void **)&rc_ent);
        yfree((void **)&entry);

        return 0;
}

static int handler(void *arg, void *lru_entry) {
        lru_entry_t *entry = (lru_entry_t *)lru_entry;
        rcache_entry_t *rc_ent = entry->value;

        printf("handler %d\n", rc_ent->chkid);
        return 0;
}

void test_lru() {
        lru_t *lru;
        rcache_entry_t *entry;

        lru_init(&lru, 10,
                 __lru_cmp_func,
                 __lru_key_func,
                 __lru_get_key_func,
                 __lru_load,
                 __lru_free);

        int key1 = 1;
        int key2 = 2;

        for (int i=0; i < 20; i++) {
                lru_get(lru, &i, (void **)&entry);
                // printf("chkid %d\n", entry->chkid);
        }

        for (int i=0; i < 30; i++) {
                lru_get(lru, &i, (void **)&entry);
                // printf("chkid %d\n", entry->chkid);
        }

        // lru_get(lru, &key2, (void **)&entry);
        // printf("chkid %d\n", entry->chkid);

        lru_get(lru, &key2, (void **)&entry);
        lru_get(lru, &key1, (void **)&entry);
        // lru_get(lru, &key2, (void **)&entry);

        lru_dump(lru, handler);

        lru_destroy(&lru);

}

int cmpfunc (const void * a, const void * b)
{
        return ( *(int*)a - *(int*)b );
}

void test_qsort() {
        int n;

        printf("Before sorting the list is: \n");
        for( n = 0 ; n < 5; n++ )
        {
                printf("%d ", values[n]);
        }
        printf("\n");

        qsort(values, 5, sizeof(int), cmpfunc);

        printf("\nAfter sorting the list is: \n");
        for( n = 0 ; n < 5; n++ )
        {
                printf("%d ", values[n]);
        }
        printf("\n");

}

int main()
{
        test_lru();
        return(0);
}
